﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.QueryParsers;
using Lucene.Net.Search;
using System.Runtime.Remoting;
using Lucene.Net.Store;

namespace CommonSearchModule
{
    public class Search
    {
        private string _IndexPath;
        private QueryTerm _Term;

        public Search(string indexPath, QueryTerm term)
        {
            _IndexPath = indexPath;
            _Term = term;
        }

        public SearchResult GetSearchResult()
        {
            IndexSearcher searcher = new IndexSearcher(_IndexPath);//本地
            SearchResult result = new SearchResult();
            StandardAnalyzer analyzer = new StandardAnalyzer();
            Stopwatch watch = new Stopwatch();

            try
            {
                Hits hits = null;
                Query query = GetQuery();

                watch.Start();

                if (query == null)
                {
                    query = new QueryParser(FieldKeys.SearchKey, analyzer).Parse("key");
                }
                //Sort sort = new Sort("ID"); //排序依据
                // string[] sortOrder = { "ID", "Name" }; //多字段排序
                //Sort sort = new Sort("ID",true); //倒序排序\
                //SortField[] sortorder = { new SortField("ID"), new SortField("Name", true) };  Sort sort = new Sort(sortorder); //按ID的asc而name为desc方式排序
                //    hits = searcher.Search(query, sort);
                hits = searcher.Search(query);
                watch.Stop();
                result.Result = GetResult(hits);
                result.RunTime = watch.Elapsed;
                result.Total = hits.Length();
            }
            finally
            {
                searcher.Close();
            }

            return result;
        }

        private IList<Search_Entity> GetResult(Hits hits)
        {
            int start = (_Term.PageIndex - 1) * _Term.PageSize;
            int end;
            if (_Term.PageIndex * _Term.PageSize < hits.Length())
            {
                end = _Term.PageIndex * _Term.PageSize;
            }
            else
            {
                end = hits.Length();
            }

            IList<Search_Entity> lists = new List<Search_Entity>();

            for (int i = start; i < end; i++)
            {
                Document doc = new Document();
                doc = hits.Doc(i);

                Search_Entity view = new Search_Entity();
                view.ID = doc.Get(FieldKeys.ID);
                view.Name = string.IsNullOrEmpty(doc.Get(FieldKeys.Name)) ? doc.Get(FieldKeys.Name) : SetHighLighter(_Term.KeyWord, doc.Get(FieldKeys.Name));
                view.Info = string.IsNullOrEmpty(doc.Get(FieldKeys.Info)) ? doc.Get(FieldKeys.Info) : SetHighLighter(_Term.KeyWord, doc.Get(FieldKeys.Info));
                view.CategoryName = string.IsNullOrEmpty(doc.Get(FieldKeys.CategoryName)) ? doc.Get(FieldKeys.CategoryName) : SetHighLighter(_Term.KeyWord, doc.Get(FieldKeys.CategoryName));
                view.PackageTime = string.IsNullOrEmpty(doc.Get(FieldKeys.PackageTime)) ? doc.Get(FieldKeys.PackageTime) : SetHighLighter(_Term.KeyWord, doc.Get(FieldKeys.PackageTime));
                view.PropertyName = string.IsNullOrEmpty(doc.Get(FieldKeys.PropertyName)) ? doc.Get(FieldKeys.PropertyName) : SetHighLighter(_Term.KeyWord, doc.Get(FieldKeys.PropertyName));
                lists.Add(view);
            }
            return lists;
        }

        private string SetHighLighter(string keyword, string text)
        {
            string startTag = "{starttag}";
            string endTag = "{endtag}";

            if (string.IsNullOrEmpty(keyword)) return text;
            //关键字中英文拆分
            string[] strs = keyword.Split(' ');

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < strs.Length; i++)
            {

                int _Kindex = text.ToLower().IndexOf(strs[i].ToLower());

                if (_Kindex != -1)
                {
                    string replaceKW = text.Substring(_Kindex, strs[i].Length);
                    text = Regex.Replace(text, replaceKW, string.Format("{0}{1}{2}", startTag, replaceKW, endTag), RegexOptions.IgnoreCase);
                }
            }
            text = text.Replace(startTag, "<font color=\"#C60A00\">").Replace(endTag, "</font>");
            return text;
        }

        private Query GetQuery()
        {
            if (_Term.IsNullQuery()) return null;

            Query query = null;
            StandardAnalyzer analyzer = new StandardAnalyzer();

            BooleanQuery bquery = new BooleanQuery();

            if (!string.IsNullOrEmpty(_Term.KeyWord))
            {
                //关键字中英文拆分
                string strKW = _Term.KeyWord;
                MultiFieldQueryParser mqp = new MultiFieldQueryParser(SearchConfig.KeywordFields, analyzer);
                mqp.SetDefaultOperator(QueryParser.Operator.OR);
                if (strKW.IndexOf(' ') != -1) strKW = strKW.Replace(" ", " AND ");
                query = mqp.Parse(strKW);
                bquery.Add(query, BooleanClause.Occur.MUST);
            }
            if (!string.IsNullOrEmpty(_Term.CategoryName))
            {
                //分类
                MultiFieldQueryParser mqp = new MultiFieldQueryParser(SearchConfig.CategoryNameFields, analyzer);
                query = mqp.Parse(_Term.CategoryName);
                bquery.Add(query, BooleanClause.Occur.MUST);
            }
            if (!string.IsNullOrEmpty(_Term.PropertyName))
            {
                //属性
                string strProperty = _Term.PropertyName;
                MultiFieldQueryParser mqp = new MultiFieldQueryParser(SearchConfig.PropertyNameFields, analyzer);
                //mqp.SetDefaultOperator(QueryParser.Operator.OR); //几个字段之间用and 还是 or 
                if (strProperty.IndexOf('|') != -1) strProperty = strProperty.Replace("|", " AND ");//几个参数之间
                query = mqp.Parse(strProperty);
                bquery.Add(query, BooleanClause.Occur.MUST);
            }
            return bquery;
        }
    }
}